package chat.server;

import java.io.Serializable;
import java.nio.channels.SelectionKey;
import java.util.HashMap;
import java.util.concurrent.Semaphore;

import chat.State;
import chat.client.statemachine.chat.ChatMessageContent;
import chat.server.statemachine.mutex.MutexTokenContent;
import chat.server.statemachine.termin.TerminColor;
import chat.server.statemachine.termin.TerminTokenContent;

public class ChatServerState extends State{
	public SelectionKey currKey;
	
	public ChatSelectorMultiServerMain server;
	public int identity;
	public int seqNumber;
	public Semaphore semaphore = new Semaphore(1);
	
	/* Related to election */
	public Integer caw;
	public Integer win;
	public int rec = 0;
	public int lrec = 0;
	public Integer father;
	public SelectionKey fatherKey;
	public ChatServerElectionState state = ChatServerElectionState.Unknown;
	
	/* Related to identity */
	public HashMap<Integer,SelectionKey> neighbors = new HashMap<Integer,SelectionKey>();
	
	/* Related to mutex */
	public int ns = 0;
	public boolean waitingForMutexToken = false;
	public boolean hasToken = false;
	public HashMap<Integer,Integer> dem = new HashMap<Integer,Integer>();
	public MutexTokenContent mutexTokenContent; 
	public int numOfNeigh = 0;
	
	/* Related to detection of terminaison */
	public TerminColor color = TerminColor.WHITE;
	public boolean active = false;
	public int mc = 0;
	public ChatServerTermin cst;
	public Semaphore TerminSemaphore = new Semaphore(0);
	
	/**
	 * Reset election related data to allow a new election
	 */
	public void resetElectionState() {
		caw = null;
		//win = null;
		rec = 0;
		lrec = 0;
		father = 0;
		
		//state = ChatServerElectionState.Unknown;
	}
	/**
	 * Update terminaison related state when sending a message
	 */
	public void updateTerminStateOnReceive() {
		active = true;
		mc--;
		color = TerminColor.BLACK;
	}
	/**
	 * 
	 * @param s The message sended
	 */
	public void updateTerminStateOnSend(Serializable s) {
		if (!(s instanceof TerminTokenContent) && !(s instanceof ChatMessageContent)) {
			mc++;
		}
	}
	/**
	 * Return identity of next server
	 * Start identifier of server : 0
	 * 
	 */
	public int getNext() {
		return (identity == numOfNeigh) ? 0 : identity + 1;
	}
}
